package com.xiaohe66.web.application.task;

import com.xiaohe66.common.util.IdWorker;
import com.xiaohe66.common.value.Paging;
import com.xiaohe66.common.ex.BusinessException;
import com.xiaohe66.common.value.ErrorCodeEnum;
import com.xiaohe66.common.web.sec.annotation.NeedLogin;
import com.xiaohe66.common.web.validator.annotation.Verify;
import com.xiaohe66.web.application.task.bo.TaskChangePoolBo;
import com.xiaohe66.web.application.task.bo.TaskListBo;
import com.xiaohe66.web.application.task.bo.TaskSaveBo;
import com.xiaohe66.web.application.task.bo.TaskSortBo;
import com.xiaohe66.web.application.task.convert.TaskBoConverter;
import com.xiaohe66.web.application.task.result.TaskDetailResult;
import com.xiaohe66.web.application.task.result.TaskResult;
import com.xiaohe66.web.domain.account.value.AccountId;
import com.xiaohe66.web.domain.sys.sec.service.SecurityService;
import com.xiaohe66.web.domain.task.agg.Task;
import com.xiaohe66.web.domain.task.entity.TaskPool;
import com.xiaohe66.web.domain.task.repository.TaskRepository;
import com.xiaohe66.web.domain.task.service.TaskService;
import com.xiaohe66.web.domain.task.value.TaskChangeTime;
import com.xiaohe66.web.domain.task.value.TaskId;
import com.xiaohe66.web.domain.task.value.TaskPoolId;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author xiaohe
 * @since 2021.11.17 14:38
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class TaskAppService {

    private final TaskBoConverter converter;

    private final TaskService taskService;
    private final TaskRepository taskRepository;
    private final SecurityService securityService;

    @Verify
    @NeedLogin
    public Long save(TaskSaveBo saveBo) {

        AccountId accountId = securityService.getCurrentAccountId();

        if (saveBo.getId() == null) {
            saveBo.setId(IdWorker.genId());
        }
        Task task = converter.toAgg(saveBo, accountId);
        taskService.saveTask(task);

        return saveBo.getId();
    }

    @NeedLogin
    public void remove(Long id) {

        TaskId taskId = new TaskId(id);
        taskService.removeById(taskId);
    }

    @Verify
    @NeedLogin
    public void changeStatus(TaskChangePoolBo poolBo) {

        TaskId taskId = new TaskId(poolBo.getTaskId());
        TaskPoolId poolId = new TaskPoolId(poolBo.getPoolId());
        TaskChangeTime changeTime = new TaskChangeTime(poolBo.getChangeTime() == null ? LocalDateTime.now() : poolBo.getChangeTime());

        taskService.changePool(taskId, poolId, changeTime);
    }

    @Verify
    @NeedLogin
    public void sort(TaskSortBo sortBo) {

        TaskPoolId poolId = new TaskPoolId(sortBo.getPoolId());

        List<TaskId> taskIdList = sortBo.getTaskIds().stream()
                .map(TaskId::new)
                .toList();

        taskService.sort(poolId, taskIdList);
    }

    /**
     * 用于页面的首次获取
     */
    @NeedLogin
    public List<List<TaskResult>> queryLists() {

        AccountId currentAccountId = securityService.getCurrentAccountId();

        List<TaskPool> taskPools = TaskPool.defaultPool();

        List<List<TaskResult>> resultList = new ArrayList<>(taskPools.size());

        Paging paging = new Paging(0L, 10);
        for (int i = 0; i < taskPools.size(); i++) {

            Paging paging1 = i == 2 ? new Paging(0L, 20) : paging;

            List<Task> tasks = taskRepository.listByPoolId(currentAccountId, taskPools.get(i).getId(), paging1);
            resultList.add(converter.toResult(tasks));
        }

        return resultList;
    }

    @Verify
    @NeedLogin
    public List<TaskResult> queryList(TaskListBo bo) {

        AccountId currentAccountId = securityService.getCurrentAccountId();

        TaskPoolId poolId = new TaskPoolId(bo.getPoolId());

        List<Task> tasks = taskRepository.listByPoolId(currentAccountId, poolId, bo.toPaging());
        return converter.toResult(tasks);
    }

    @NeedLogin
    public TaskDetailResult queryDetail(Long id) {

        Task task = taskRepository.getById(new TaskId(id));
        if (task == null) {
            throw new BusinessException(ErrorCodeEnum.NOT_FOUND);
        }

        return converter.toDetail(task);
    }
}
